package com.shopping.config;

import com.shopping.filters.ShoppingBasicAuthenticationFilter;
import com.shopping.handler.LoginFailureHandler;
import com.shopping.handler.LoginSuccessHandler;
import com.shopping.handler.LogoutSuccessHandlerImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;

import javax.annotation.Resource;


/**
 * SpringSecurity配置类
 */
@Configuration
public class SecurityConfig {
    @Resource
    private UserDetailsService userDetailsService;
    @Resource
    private AuthenticationConfiguration authenticationConfiguration;
    /**
     * 用于拦截请求，并对请求进行处理
     * @param httpSecurity
     * @return  SecurityFilterChain:Security过滤器链
     */
    @Bean
    @Autowired
    public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {
        httpSecurity
                .csrf().disable()//禁止跨域伪造访问
                //security默认禁止跨域请求
                .cors()
                .and()
                .authorizeRequests()//获得请求
                    .antMatchers("/book/*","/register")
                        .permitAll()//无需认证直接访问
                    .anyRequest()//所有请求
                         .authenticated()//必须认证才能访问
             .and()
                //配置登陆页form表单
                .formLogin()//配置表单
                    .loginProcessingUrl("/login")//使用重定向方式配置登陆处理器的url地址，该地址所对应处理类由SpringSecurity提供
                    .loginPage("http://localhost:8080/#/login")//配置登陆页
                    .successHandler(new LoginSuccessHandler())//成功处理器，成功后跳转到指定处理器
                    .failureHandler(new LoginFailureHandler())
             .and()
                .logout()//退出配置
                    .logoutUrl("/exit")//退出地址
                    .invalidateHttpSession(true)//退出销毁session
                    .logoutSuccessHandler(new LogoutSuccessHandlerImpl())//退出成功的处理器
        ;
        httpSecurity.addFilter(new ShoppingBasicAuthenticationFilter(authenticationConfiguration.getAuthenticationManager()));

        return httpSecurity.build();//获得securityFilterChain的实现类对象并返回
    }

    /**
     * 注入认证处理器
     * @param builder
     * @throws Exception
     */
    @Autowired
    public void registerProvider(AuthenticationManagerBuilder builder) throws Exception{
        //创建认证处理器对象
        DaoAuthenticationProvider daoAuthenticationProvider =new DaoAuthenticationProvider();
        //开启该异常
        daoAuthenticationProvider.setHideUserNotFoundExceptions(false);
        daoAuthenticationProvider.setUserDetailsService(userDetailsService);
        daoAuthenticationProvider.setPasswordEncoder(new BCryptPasswordEncoder());
        builder.authenticationProvider(daoAuthenticationProvider);//将该认证处理器交给SpringSecurity
                //如上配置后下面设置无效
           /*builder.userDetailsService(userDetailsService)
                   .passwordEncoder(new BCryptPasswordEncoder());*/
    }

}